﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System.Data;
using System.Data.Objects;
using System.Configuration;
using System.Data.Common;
using System.Transactions;
using System.Data.EntityClient;
using System.Data.Metadata.Edm;
using System.Diagnostics;

namespace Fdd.Aspen.Infrastructure.Data
{
    public class DefaultObjectContextFactory : IObjectContextFactory
    {

        public ObjectContext Create()
        {
            return this.Create(ConfigurationManager.ConnectionStrings["AspenConnectionString"].ConnectionString);
        }


        public ObjectContext Create(string connectionString)
        {
            if (string.IsNullOrEmpty(connectionString))
                throw new ArgumentNullException("connectionString");

            var connection = new SqlConnection(connectionString);

            var workspace = new MetadataWorkspace(
                                    new string[] { "res://*/" },
                                    new Assembly[] { GetModelMappingConfigurationAssembly() });

            CheckAndBeSureMetadataIsLoaded(workspace);

            return this.Create(new EntityConnection(workspace, connection));
        }



        private ObjectContext Create(EntityConnection con)
        {
            if (con == null)
                throw new ArgumentNullException("con");

            return new ObjectContext(con);
        }


        private static void CheckAndBeSureMetadataIsLoaded(MetadataWorkspace workspace)
        {
            Debug.Assert(workspace.GetItemCollection(DataSpace.CSpace).GetItems<EntityType>().Count != 0);
            Debug.Assert(workspace.GetItemCollection(DataSpace.SSpace).GetItems<EntityType>().Count != 0);
        }


        private Assembly GetModelMappingConfigurationAssembly()
        {
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

            var assembly = assemblies.Where(a => a.FullName.Contains("EntityMapping")).SingleOrDefault();

            if (assembly == null)
                throw new MappingException("Can't find the Assembly with the Entity Configuration Mapping");

            return assembly;
        }
    }
}
